package com.ebeitech.auction.db;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.ebeitech.auction.db.annotation.Column;
import com.ebeitech.auction.db.annotation.Id;
import com.ebeitech.auction.db.annotation.Table;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by alice on 2017/10/24.
 */
public class DBOperateSQLiteHelper {

	private static final String TAG = "DBOperateSQLiteHelper";

	/**
	 * 根据映射的对象创建表.
	 *
	 * @param <T> the generic type
	 * @param db 数据库对象
	 * @param clazzs 对象映射
	 */
	public static <T> void createTablesByClasses(SQLiteDatabase db, Class<?>[] clazzs) {
		for (Class<?> clazz : clazzs){
			createTable(db, clazz);
		}
	}

	/**
	 * 根据映射的对象删除表.
	 *
	 * @param <T> the generic type
	 * @param db 数据库对象
	 * @param clazzs 对象映射
	 */
	public static <T> void dropTablesByClasses(SQLiteDatabase db,Class<?>[] clazzs) {
		for (Class<?> clazz : clazzs){
			dropTable(db, clazz);
		}
	}

	/**
	 * 创建表
	 * @param db
	 * @param clazz
	 * @param <T>
	 */
	public static <T> void createTable(SQLiteDatabase db,Class<T> clazz){
		String tableName = "";
		if(clazz.isAnnotationPresent(Table.class)){
			Table table = (Table) clazz.getAnnotation(Table.class);
			tableName = table.name();
		}
		if(tableName == null || tableName.trim().length() == 0){
			Log.d(TAG, "想要映射的实体["+clazz.getName()+"],未注解@Table(name=\"?\"),被跳过");
			return;
		}
		if(checkIfTableExist(db,tableName)){
			return;
		}

		StringBuilder sb = new StringBuilder();
		sb.append("CREATE TABLE ").append(tableName).append(" (");
		List<Method> methods = joinMethods(clazz.getDeclaredMethods());
		for(Method m : methods) {
			if (!m.isAnnotationPresent(Column.class)) {
				continue;
			}
			Column column = (Column) m.getAnnotation(Column.class);
			String columnType = "";
			if (column.type().equals(""))
				columnType = getColumnType(m.getReturnType());
			else {
				columnType = column.type();
			}

			sb.append(column.name() + " " + columnType);

			if (column.length() != 0) {
				sb.append("(" + column.length() + ")");
			}

			if (!"".equals(column.defaultValue())) {
				sb.append(" DEFAULT " + column.defaultValue());
			}

			//实体类定义为Integer类型后不能生成Id异常
			if ((m.isAnnotationPresent(Id.class))){
				sb.append(" primary key autoincrement");
			}

			sb.append(", ");
		}
		sb.delete(sb.length() - 2, sb.length() - 1);
		sb.append(")");

		String sql = sb.toString();

		Log.d(TAG, "create table [" + tableName + "]: " + sql);

		db.execSQL(sql);
	}

	/**
	 * 删除表
	 * @param db
	 * @param clazz
	 * @param <T>
	 */
	public static <T> void dropTable(SQLiteDatabase db, Class<T> clazz) {
		String tableName = "";
		if (clazz.isAnnotationPresent(Table.class)) {
			Table table = (Table) clazz.getAnnotation(Table.class);
			tableName = table.name();
		}
		String sql = "DROP TABLE IF EXISTS " + tableName;
		Log.d(TAG, "dropTable[" + tableName + "]:" + sql);
		db.execSQL(sql);
	}

	public static <T> void createColumnByClasses(SQLiteDatabase db , Class<?>[] clazzs){
		for (Class<?> clazz: clazzs){
			addColumn(db,clazz);
		}
	}
	/**
	 * 更新添加 新的字段
	 * @param db
	 * @param clazz
	 * @param <T>
	 */
	public static <T> void addColumn(SQLiteDatabase db, Class<T> clazz){
		String tableName = "";
		if(clazz.isAnnotationPresent(Table.class)){
			Table table = (Table) clazz.getAnnotation(Table.class);
			tableName = table.name();
		}
		if(tableName == null || tableName.trim().length() == 0){
			Log.d(TAG, "想要映射的实体["+clazz.getName()+"],未注解@Table(name=\"?\"),被跳过");
			return;
		}
		List<Method> methods = joinMethods(clazz.getDeclaredMethods());

		for (Method method : methods){
			if(!method.isAnnotationPresent(Column.class)){
				continue;
			}
			Column column = (Column) method.getAnnotation(Column.class);
			if(checkIfColumnExist(db,tableName,column.name())){
				continue;
			}
			StringBuffer sb = new StringBuffer();
			sb.append(" ALTER TABLE ").append(tableName).append(" ADD ");
			String columnType = "";
			if(column.type().equals("")){
				columnType = getColumnType(method.getReturnType());
			}else{
				columnType = column.type();
			}

			sb.append(column.name() + " " + columnType);

			if(column.length() != 0){
				sb.append("(" + column.length() + ")");
			}

			if(!"".equals(column.defaultValue())){
				sb.equals(" DEFAULT " + column.defaultValue());
			}

			//实体类定义为Integer类型后不能生成Id异常
			if ((method.isAnnotationPresent(Id.class))){
				sb.append(" primary key autoincrement");
			}

			sb.append(" ;");
			String sql = sb.toString();

			Log.d(TAG, "add column [" + column.name() + "]: " + sql);

			db.execSQL(sql);
		}
	}

	/**
	 * 获取Column 方法
	 * @param methods
	 * @return
	 */
	public static List<Method> joinMethods(Method[] methods){
		Map<String,Method> map = new LinkedHashMap<String,Method>();
		for(Method m : methods){
			if(m.isAnnotationPresent(Column.class)){
				Column column = (Column) m.getAnnotation(Column.class);
				map.put(column.name(), m);
			}
		}
		List<Method> list = new ArrayList<Method>();
		for(String key : map.keySet()){
			Method temp = map.get(key);
			if(temp.isAnnotationPresent(Id.class)){
				list.add(0,temp);
			}else{
				list.add(temp);
			}
		}
		return list;
	}

	/**
	 * 获取列类型
	 * @param fieldType
	 * @return
	 */
	private static String getColumnType(Class<?> fieldType) {
		if (String.class == fieldType) {
			return "TEXT";
		}
		if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
			return "INTEGER";
		}
//        if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
//            return "BIGINT";
//        }
//        if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
//            return "FLOAT";
//        }
//        if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
//            return "INT";
//        }
//        if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
//            return "DOUBLE";
//        }

		return "TEXT";
	}

	/**
	 * 判断字段是否存在
	 * @param db
	 * @param tableName
	 * @param columnName
	 * @return
	 */
	private static boolean checkIfColumnExist(SQLiteDatabase db, String tableName,String columnName) {
		boolean result = false;
		Cursor cursor = null;

		try {
			cursor = db.rawQuery("select * from sqlite_master where name = ? and sql like ?",
					new String[] { tableName, "%" + columnName + "%" });
			result = (null != cursor) && cursor.moveToFirst();
		} catch (Exception e) {
			Log.e(TAG, "checkIfColumnExist..." + e.getMessage());
		} finally {
			if (null != cursor && !cursor.isClosed()) {
				cursor.close();
			}
		}
		return result;
	}

	/**
	 * 判断表是否存在
	 * @param db
	 * @param tableName
	 * @return
	 */
	private static boolean checkIfTableExist(SQLiteDatabase db,String tableName){
		boolean result = false;
		Cursor cursor = null;

		try {
			cursor = db.rawQuery("select * from sqlite_master where type='table' and name= ?",new String[] { tableName });
			result = (null != cursor) && cursor.moveToFirst();
		} catch (Exception e) {
			Log.e(TAG, "checkIfTableExist..." + e.getMessage());
		} finally {
			if (null != cursor && !cursor.isClosed()) {
				cursor.close();
			}
		}
		return result;
	}

}
